package top.codermao.stock.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import top.codermao.stock.mapper.StockMarketIndexInfoMapper;
import top.codermao.stock.pojo.entity.StockMarketIndexInfo;
import top.codermao.stock.pojo.vo.StockInfoConfig;
import top.codermao.stock.service.StockTimerTaskService;
import top.codermao.stock.utils.DateTimeUtil;
import top.codermao.stock.utils.IdWorker;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author msk
 * @date 2024/5/4 21:16
 * @Description
 */
@Service
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Override
    public void getInnerMarketInfo() {
        //1.阶段一：采集原始数据
        //1.1组装url地址
        //http://hq.sinajs.cn/list=sh000001,sz399001
        String url = stockInfoConfig.getMarketUrl() + String.join(",", stockInfoConfig.getInner());
        //1.2维护请求头
        HttpHeaders headers = new HttpHeaders();
        //防盗链
        headers.add("Referer", "https://finance.sina.com.cn/stock/v");
        //用户客户端标识
        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36");
        //1.3.维护http请求对象
        HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
        //1.4发送请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        int statusCodeValue = responseEntity.getStatusCodeValue();
        if (statusCodeValue != 200) {
            //当前请求失败
            log.error("当前时间点:{},采集数据失败，http状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"), statusCodeValue);
            //其他事情，例如发送邮件 企业微信 顶顶给运维人员提醒
            return;
        }
        //获取js格式数据
        String jsData = responseEntity.getBody();
        log.info("当前时间点：{}，采集原始数据内容：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"), jsData);

        //2.阶段二：java正则解析元素数据
//        var hq_str_sh000001="上证指数,3110.1594,3113.0432,3104.8245,3123.2876,3104.2943,0,0,440213213,473803228531,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2024-04-30,15:30:39,00,";
//        var hq_str_sz399001="深证成指,9647.056,9673.758,9587.124,9662.558,9587.076,0.000,0.000,52697389055,556846038511.444,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2024-04-30,15:00:03,00";
        //2.1定义正则表达式
        String reg = "var hq_str_(.+)=\"(.+)\";";
        //2.2表达式编译
        Pattern pattern = Pattern.compile(reg);
        //2.3匹配字符串
        Matcher matcher = pattern.matcher(jsData);
        List<StockMarketIndexInfo> entities = new ArrayList<>();
        while (matcher.find()) {
            //1.获取大盘的编码
            String marketCode = matcher.group(1);
            //2.获取其他信息
            String otherInfo = matcher.group(2);
            //将other字符串以逗号切割
            String[] splitArr = otherInfo.split(",");
            //大盘名称
            String marketName = splitArr[0];
            //获取当前大盘的开盘点数
            BigDecimal openPoint = new BigDecimal(splitArr[1]);
            //前收盘点
            BigDecimal preClosePoint = new BigDecimal(splitArr[2]);
            //获取大盘的当前点数
            BigDecimal curPoint = new BigDecimal(splitArr[3]);
            //获取大盘最高点
            BigDecimal maxPoint = new BigDecimal(splitArr[4]);
            //获取大盘的最低点
            BigDecimal minPoint = new BigDecimal(splitArr[5]);
            //获取成交量
            Long tradeAmt = Long.valueOf(splitArr[8]);
            //获取成交金额
            BigDecimal tradeVol = new BigDecimal(splitArr[9]);
            //时间
            Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
            //3.阶段三：解析数据封装entity
            StockMarketIndexInfo entity = StockMarketIndexInfo.builder()
                    .id(idWorker.nextId())
                    .marketName(marketName)
                    .openPoint(openPoint)
                    .preClosePoint(preClosePoint)
                    .curPoint(curPoint)
                    .maxPoint(maxPoint)
                    .minPoint(minPoint)
                    .tradeAmount(tradeAmt)
                    .tradeVolume(tradeVol)
                    .marketCode(marketCode)
                    .curTime(curTime)
                    .build();
            entities.add(entity);
        }
        log.info("解析大盘数据完毕");
        //4.阶段四：调用mybatis，批量入库
        int count = stockMarketIndexInfoMapper.insertBath(entities);
        if (count > 0){
            log.info("当前时间：{}，插入数据：{}成功",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),entities);
        }else {
            log.error("当前时间：{}，插入数据：{}失败",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),entities);
        }
    }
}
